# coding=utf-8
import os
import subprocess

from appium import webdriver
from time import sleep, time
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from colorama import init, Fore, Style
init(autoreset=True)

# 配置参数
CONFIG = {
    "platformName": "Android",
    "automationName": "uiautomator2",
    "platformVersion": "9",
    "deviceName": '2025061700001872',
    "appPackage": "com.seven.qaml.burstserven",
    "appActivity": "com.seven.qaml.burstserven.ui.MenuActivity",
    'skipServerInstallation': False,
    'skipDeviceInitialization': False,
    "noReset": True,
    "max_attempts": 100,  # 最大尝试次数
    "default_wait_time": 10,  # 默认等待时间
    "command_timeout": 30  # 命令超时时间
}

appium_server_url = 'http://127.0.0.1:4723'

# 元素定位器
ELEMENTS = {
    "layout_zuWang": (By.ID, 'com.seven.qaml.burstserven:id/layout_zuWang'),
    "text_sign": (By.ID, 'com.seven.qaml.burstserven:id/text_sign'),
    "tv_message": (By.ID, 'com.seven.qaml.burstserven:id/tv_message'),
    "btn_authnext": (By.ID, 'com.seven.qaml.burstserven:id/btn_authnext'),
    "charge_text": (By.XPATH, '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.widget.TextView[4]'),
    "qibao_text": (By.XPATH, '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.widget.LinearLayout[1]/android.widget.TextView[1]')
}

def initialize_driver(retries=3):
    """初始化Appium驱动"""
    for attempt in range(retries):
        try:
            print(f"正在初始化Appium驱动... (尝试 {attempt + 1}/{retries})")
            driver = webdriver.Remote(appium_server_url, CONFIG)
            print("Appium驱动初始化成功")
            return driver
        except Exception as e:
            print(f"{Fore.RED}初始化Appium驱动失败: {e}")
            if attempt < retries - 1:
                print("等待5秒后重试...")
                sleep(5)
            else:
                print(f"{Fore.RED}经过 {retries} 次尝试后仍无法初始化驱动")
    return None

def setup_adb_script():
    """设置ADB脚本"""
    adb_script_path = "/data/local/press_keys.sh"
    adb_command = f'adb shell {adb_script_path}'
    adb_check_command = f"adb shell ls {adb_script_path}"
    
    result = subprocess.run(adb_check_command, shell=True, capture_output=True, text=True)
    if result.returncode == 0:
        print("获取到起爆脚本:", adb_script_path)
    else:
        print('未获取到起爆脚本，正在创建......')
        create_script_command = (
            'adb shell "echo \'for i in $(seq 1 5); do input keyevent 999 & input keyevent 132; done\' > '
            '/data/local/press_keys.sh && chmod 755 /data/local/press_keys.sh"'
        )
        subprocess.run(create_script_command, shell=True)
        print("创建起爆脚本成功：", adb_script_path)
        
    return adb_command

def wait_and_click_element(driver, locator_key, timeout=10):
    """等待并点击元素"""
    try:
        element = WebDriverWait(driver, timeout).until(
            EC.element_to_be_clickable(ELEMENTS[locator_key])
        )
        element.click()
        return True
    except TimeoutException:
        print(f"{Fore.RED}等待元素 {locator_key} 超时")
        return False
    except Exception as e:
        print(f"{Fore.RED}点击元素 {locator_key} 出现异常: {e}")
        return False

def safe_keyevent(driver, keycode, retries=3):
    """安全地发送按键事件"""
    for attempt in range(retries):
        try:
            driver.keyevent(keycode)
            return True
        except Exception as e:
            print(f"{Fore.YELLOW}发送按键事件 {keycode} 失败 (尝试 {attempt + 1}/{retries}): {e}")
            if attempt < retries - 1:# 不是最后一次重试才会执行，避免立即重试
                sleep(1)
    return False

def detonate_process(driver, adb_command):
    """执行一次起爆过程"""
    # 点击组网起爆
    if not wait_and_click_element(driver, "layout_zuWang"):
        return False
    
    sleep(5)
    
    # 等待扫描准备完成并在准备好时发送确定键事件开始扫描
    # 设置扫描超时时间为300秒(5分钟)
    scan_start_time = time()
    scan_timeout = 300  # 300秒超时
    # 循环检查扫描准备状态直到超时
    while time() - scan_start_time < scan_timeout:
        try:
            # 查找文本标识元素
            element = driver.find_element(*ELEMENTS["text_sign"])
            # 检查元素文本是否为准备完成状态
            if element.text == "准备完成，按‘确定’键开始扫描":
                # 发送确定键事件(键码66)开始扫描
                if safe_keyevent(driver, 66):
                    # print("等待扫描结果...")
                    break  # 成功发送按键事件，退出循环
                else:
                    return False  # 发送按键事件失败，返回False
        except NoSuchElementException:
            # 未找到元素，等待1秒后继续尝试
            sleep(1)
            continue
        except Exception as e:
            # 处理其他异常情况
            print(f"{Fore.YELLOW}检查扫描准备状态时出错: {e}")
            sleep(1)
            continue
    else:
        # 循环正常结束表示超时未检测到准备完成状态
        print(f"{Fore.RED}等待扫描准备超时")
        return False
    
    # 等待扫描完成
    scan_complete_start_time = time()
    scan_complete_timeout = 600  # 600秒超时
    while time() - scan_complete_start_time < scan_complete_timeout:
        try:
            elements = driver.find_elements(*ELEMENTS["tv_message"])
            if elements and elements[0].text == '按F1查看列表，确定键继续':
                print("（1/5）扫描完成")
                if not safe_keyevent(driver, 66):
                    return False
                sleep(2)
                break
        except Exception as e:
            print(f"{Fore.YELLOW}检查扫描完成状态时出错: {e}")
            sleep(1)
            continue
    else:
        print(f"{Fore.RED}等待扫描完成超时")
        return False
    
    # 等待继续按钮
    auth_found = False
    auth_start_time = time()
    auth_timeout = 60  # 60秒超时
    while time() - auth_start_time < auth_timeout:
        try:
            authnext_element = WebDriverWait(driver, 1).until(
                EC.presence_of_element_located(ELEMENTS["btn_authnext"])
            )
            if authnext_element.text == '按确定键继续':
                if safe_keyevent(driver, 66):
                    print("（2/5）验证完成")
                    sleep(2)
                    auth_found = True
                    break
                else:
                    return False
        except TimeoutException:
            sleep(1)
            continue
        except Exception as e:
            print(f"{Fore.YELLOW}检查继续按钮时出错: {e}")
            sleep(1)
            continue
    
    if not auth_found:
        print("等待'按确定键继续'按钮超时")
        return False
    
    # 开始充电
    charge_found = False
    charge_start_time = time()
    charge_find_timeout = 60  # 60秒超时
    while time() - charge_start_time < charge_find_timeout:
        try:
            charge_text = driver.find_element(*ELEMENTS["charge_text"])
            if charge_text.text == '按充电键开始充电':
                if safe_keyevent(driver, 300):
                    print("（3/5）开始充电")
                    charge_found = True
                    break
                else:
                    return False
        except NoSuchElementException:
            sleep(1)
            continue
        except Exception as e:
            print(f"{Fore.YELLOW}查找充电文本时出错: {e}")
            sleep(1)
            continue
    
    if not charge_found:
        print("未找到充电文本元素或超时")
        return False
    
    # 等待充电完成并执行起爆
    charging_complete = False
    charging_start_time = time()
    charging_timeout = 300  # 最多等待300秒
    while time() - charging_start_time < charging_timeout:
        try:
            qibao_text = WebDriverWait(driver, 1).until(
                EC.presence_of_element_located(ELEMENTS["qibao_text"])
            )
            if qibao_text.text == '倒计时：':
                print("（4/5）充电完成")
                result = os.system(adb_command)
                if result == 0:
                    print("（5/5）起爆完成")
                    charging_complete = True
                    break
        except Exception as e:
            # 忽略查找过程中的异常，继续等待
            sleep(1)
            continue
    else:
        print("等待充电完成超时")
        return False
    
    sleep(10)
    return True

def reconnect_driver():
    """尝试重新连接驱动"""
    print("尝试重新连接...")
    return initialize_driver()

def main():
    """主函数"""
    # 初始化驱动
    driver = initialize_driver()
    if not driver:
        return
    
    try:
        # 设置ADB脚本
        adb_command = setup_adb_script()
        
        # 执行起爆循环
        count = 0
        while count < CONFIG["max_attempts"]:
            print(f"\n开始第 {count + 1} 次起爆...")
            
            try:
                success = detonate_process(driver, adb_command)
                if success:
                    count += 1
                    print(Fore.GREEN + f"已完成 {count} 次起爆")
                else:
                    print(Fore.RED + f"第 {count + 1} 次起爆失败")
                    # 尝试重新初始化驱动
                    try:
                        driver.quit()
                    except:
                        pass
                    
                    driver = reconnect_driver()
                    if not driver:
                        choice = input("是否继续？(y/n): ")
                        if choice.lower() != 'y':
                            break
                        continue
            except Exception as e:
                print(f"{Fore.RED}程序执行过程中出现异常: {e}")
                # 在出现异常时尝试重新连接
                try:
                    driver.quit()
                except:
                    pass
                
                driver = reconnect_driver()
                if not driver:
                    choice = input("是否继续？(y/n): ")
                    if choice.lower() != 'y':
                        break
                    continue
                
            sleep(10)  # 每次循环之间稍作停顿
            
    except KeyboardInterrupt:
        print("\n用户中断程序")
    except Exception as e:
        print(f"{Fore.RED}程序执行过程中出现严重异常: {e}")
    finally:
        # 关闭驱动
        try:
            driver.quit()
            print("Appium驱动已关闭")
        except Exception as e:
            print(f"{Fore.RED}关闭驱动时出现异常: {e}")

if __name__ == "__main__":
    main()